package com.veetao.api.model;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.veetao.api.consts.McpConstants;

public class ApiCommandContext implements CommandContext, Serializable {

	// private static final Log logger =
	// LogFactory.getLog(ApiCommandContext.class);

	private static final long serialVersionUID = 1L;
	
	private String locale;

	private long beginTime;

	/** 当前调用的接口名 */
	private String methodName;

	/** 当前的用户编号 */
	private int userId;
	/** 当前可能的用户编号 */
	private long userIdMybe;

	/** 客户端接入授权信息 */
	private AppClientInfo appInfo;

	/** 设备唯一标识 */
	private String deviceId;

	/** 当前用户的票 */
	private String ticket;

	/** 灰度测试的值 */
	private String ab;
	/** 接口的版本号 */
	private String v;
	/**应用的version参数*/
	private String version;

	/** 当前请求的检查标识 */
	private final String sig;

	/** 普通参数 */
	private Map<String, String> stringParams;

	/** 二进制文件 */
	private Map<String, Object> binaryParams;

	/** 请求的Http协议头 */
	private final Map<String, String> reqHeads;
	private Map<String, Object> statExtMap;

	/** 用户的IP */
	private final String clientIp;
	private AppInitData appInitData = null;

	private String buildNo;
	
	private byte[] aesKey;
//
//	public ApiCommandContext(long beginTime, AppClientInfo mcpAppInfo, int userId, Map<String, String> stringParams, Map<String, Object> binaryParams, String ticket,
//			String methodName, Map<String, String> reqHeads, String clientIp) {
//		this.beginTime = beginTime;
//		this.appInfo = mcpAppInfo;
//		this.reqHeads = reqHeads;
//		this.userId = userId;
//		this.stringParams = stringParams;
//		this.binaryParams = binaryParams;
//		this.ticket = ticket;
//		this.methodName = methodName;
//		this.clientIp = clientIp;
//		this.deviceId = stringParams.get(McpConstants.PARAM_DEVICEID);
//		if (this.deviceId == null || this.deviceId.isEmpty()) {
//			this.deviceId = stringParams.get(McpConstants.PARAM_GUID);
//		}
//		this.sig = stringParams.get(McpConstants.PARAM_SIG);
//		this.v = stringParams.get(McpConstants.PARAM_V);
//		this.aesKey = DigestUtils.md5(this.appInfo.getAppSecretKey());
//		this.setBuildNo(stringParams.get(McpConstants.PARAM_BUILD_NO));
//		this.setLon(stringParams.get(McpConstants.PARAM_LONGITUDE));
//		this.setLat(stringParams.get(McpConstants.PARAM_LATITUDE));
//		this.setChannel(stringParams.get(McpConstants.PARAM_CHANNEL));
//	}

	public ApiCommandContext(long beginTime, AppClientInfo mcpAppInfo, int userId, Map<String, String> stringParams, Map<String, Object> binaryParams, String ticket,
							 String methodName, Map<String, String> reqHeads, String clientIp,String version) {
		this.beginTime = beginTime;
		this.appInfo = mcpAppInfo;
		this.reqHeads = reqHeads;
		this.userId = userId;
		this.stringParams = stringParams;
		this.binaryParams = binaryParams;
		this.ticket = ticket;
		this.methodName = methodName;
		this.clientIp = clientIp;
		this.deviceId = stringParams.get(McpConstants.PARAM_DEVICEID);
		if (this.deviceId == null || this.deviceId.isEmpty()) {
			this.deviceId = stringParams.get(McpConstants.PARAM_GUID);
		}
		this.sig = stringParams.get(McpConstants.PARAM_SIG);
		this.v = stringParams.get(McpConstants.PARAM_V);
		this.aesKey = DigestUtils.md5(this.appInfo.getAppSecretKey());
		this.setBuildNo(stringParams.get(McpConstants.PARAM_BUILD_NO));
		this.setLon(stringParams.get(McpConstants.PARAM_LONGITUDE));
		this.setLat(stringParams.get(McpConstants.PARAM_LATITUDE));
		this.setChannel(stringParams.get(McpConstants.PARAM_CHANNEL));

		this.version = stringParams.get(McpConstants.PARAM_VERSION);
	}

	public ApiCommandContext() {
		this.clientIp = null;
		this.sig = null;
		this.reqHeads = null;
		
	}

	private String channel;

	@Override
	public long getBeginTime() {
		return beginTime;
	}

	public void setBeginTime(long beginTime) {
		this.beginTime = beginTime;
	}

	@Override
	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	@Override
	public int getUserId() {
		return userId;
	}

	/**
	 * 设置此userId时，会同时设置userIdMaybe
	 * 
	 * @param userId
	 */
	@Override
	public void setUserId(int userId) {
		this.userId = userId;
	}

	public long getUserIdMybe() {
		return userIdMybe;
	}

	public void setUserIdMybe(long userIdMybe) {
		this.userIdMybe = userIdMybe;
	}

	@Override
	public AppClientInfo getAppInfo() {
		return appInfo;
	}

	public void setMcpAppInfo(AppClientInfo mcpAppInfo) {
		this.appInfo = mcpAppInfo;
	}

	public String getDeviceId() {
		return deviceId;
	}

	@Override
	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	@Override
	public String getTicket() {
		return ticket;
	}

	public void setTicket(String ticket) {
		this.ticket = ticket;
	}

	@Override
	public Map<String, String> getStringParams() {
		return stringParams;
	}

	public void setStringParams(Map<String, String> stringParams) {
		this.stringParams = stringParams;
	}

	@Override
	public Map<String, Object> getBinaryParams() {
		return binaryParams;
	}

	public void setBinaryParams(Map<String, Object> binaryParams) {
		this.binaryParams = binaryParams;
	}

	@Override
	public int getIntParamValue(String paramName) {
		return this.getIntParamValue(paramName, 0);
	}

	@Override
	public int getIntParamValue(String paramName, int defValue) {
		return NumberUtils.toInt(stringParams.get(paramName), defValue);
	}

	@Override
	public long getLongParamValue(String paramName) {
		return this.getLongParamValue(paramName, 0);
	}

	@Override
	public long getLongParamValue(String paramName, long defValue) {
		return NumberUtils.toLong(stringParams.get(paramName), defValue);
	}

	@Override
	public String getParamValue(String paramName) {
		return stringParams.get(paramName);
	}

	@Override
	public String getSig() {
		return sig;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mid.mcp.model.CommandContext#getXForwardedFor()
	 */
	@Override
	public String getXForwardedFor() {
		return this.getHttpHead("X-Forwarded-For");
	}

	@Override
	public String toString() {
		return "ApiCommandContext [beginTime=" + beginTime + ", methodName=" + methodName + ", userId=" + userId + ", mcpAppInfo=" + appInfo + ", deviceId=" + deviceId
				+ ", ticket=" + ticket + ", sig=" + sig + ", stringParams=" + stringParams + ", binaryParams=" + binaryParams + "]";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mid.mcp.model.CommandContext#getClientIp()
	 */
	@Override
	public String getClientIp() {
		return this.clientIp;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mid.mcp.model.CommandContext#getUserAgent()
	 */
	@Override
	public String getUserAgent() {
		return this.getHttpHead("User-Agent");
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mid.mcp.model.CommandContext#getHttpHead(java.lang.String)
	 */
	@Override
	public String getHttpHead(String name) {
		if (this.reqHeads == null)
			return null;
		return this.reqHeads.get(name);
	}

	public Map<String, String> getHttpHeads() {
		return this.reqHeads;
	}

	@Override
	public long getUserIdMaybe() {
		return userIdMybe;
	}

	@Override
	public AppInitData getAppInitData() {
		return appInitData;
	}

	public void setAppInitData(AppInitData appInitData) {
		this.appInitData = appInitData;
	}

	public String getAB() {
		if (this.ab == null) {
			if (this.getDeviceId() == null || this.getDeviceId().isEmpty()) {
				this.ab = "";
			} else {
				String md5DeviceId = DigestUtils.md5Hex(this.getDeviceId().getBytes()).toLowerCase();
				this.ab = md5DeviceId.substring(md5DeviceId.length() - 1);
			}
			this.addStatExt("ab", this.ab);
		}
		return this.ab;
	}

	public void addStatExt(String extKey, Object extValue) {
		if (this.statExtMap == null) {
			this.statExtMap = new HashMap<String, Object>();
		}
		this.statExtMap.put(extKey, extValue);
	}

	public Map<String, Object> getStatExt() {
		return this.statExtMap;
	}

	@Override
	public byte[] getAesKey() {
		return this.aesKey;
	}

	@Override
	public String getV() {
		return this.v;
	}

	public String getBuildNo() {
		return buildNo;
	}

	public void setBuildNo(String buildNo) {
		this.buildNo = buildNo;
	}
	
	private String lon;
	private String lat;

	public String getLon() {
		return lon;
	}

	public void setLon(String lon) {
		this.lon = lon;
	}

	public String getLat() {
		return lat;
	}

	public void setLat(String lat) {
		this.lat = lat;
	}

	public String getChannel() {
		return channel;
	}

	public void setChannel(String channel) {
		this.channel = channel;
	}

	@Override
	public String getLocale() {
		return locale;
	}

	public void setLocale(String locale) {
		this.locale = locale;
	}
	
	private HttpServletRequest httpServletRequest;
	private HttpServletResponse httpServletResponse;

	public HttpServletRequest getHttpServletRequest() {
		return httpServletRequest;
	}

	public void setHttpServletRequest(HttpServletRequest httpServletRequest) {
		this.httpServletRequest = httpServletRequest;
	}

	public HttpServletResponse getHttpServletResponse() {
		return httpServletResponse;
	}

	public void setHttpServletResponse(HttpServletResponse httpServletResponse) {
		this.httpServletResponse = httpServletResponse;
	}


}
